﻿Imports System.Xml.Serialization
Imports System.IO
Imports Microsoft.Office.Interop.Access
Imports Microsoft.Office.Interop
Imports System.Runtime.InteropServices
Imports Microsoft.Win32

Public Class AppContext

    Private Const STR_ADP As String = ".adp"

	''' <summary>
	''' Singleton instance of app context
	''' </summary>
	Private Shared appContext As AppContext

	''' <summary>
	''' Project Information instance
	''' </summary>
	Public Property projectInfo As AccessSvnProjectInfo

	''' <summary>
	''' Complete file path to config file
	''' </summary>
	''' <remarks></remarks>
	Private _RootSVNPath As String

	''' <summary>
	''' Full path to configuration file of project
	''' </summary>
	''' <remarks></remarks>
	Private _xmlConfigFilename As String

	Private Sub New()
		'prevent direct instantiations
	End Sub

	''' <summary>
	''' Get singleton instance of AppContext
	''' </summary>
	Public Shared Function current() As AppContext
		If appContext Is Nothing Then
			appContext = New AppContext
		End If
		Return appContext

	End Function

	''' <summary>
	''' Root SVN Path is always the folder where the 
	''' configuration file resides
	''' </summary>
	Public Property RootSVNPath As String
		Get
			Return Me._RootSVNPath
		End Get

		Set(ByVal value As String)
			If IO.Directory.Exists(value) = False Then
				Throw New ApplicationException("Root SVN Path does not exist")
			End If
			Me._RootSVNPath = value
			Me._xmlConfigFilename = value & "\AccessSvnProjectInfo.xml"
			If IO.File.Exists(Me._xmlConfigFilename) Then
				Me.loadConfigFile()
			End If
		End Set

	End Property
	Public ReadOnly Property xmlConfigFilename As String
		Get
			Return Me._xmlConfigFilename
		End Get

	End Property

	''' <summary>
	''' The working file path is always in the parent directory of root svn
	''' </summary>
	Public ReadOnly Property WorkingFilePath As String
		Get
			Dim fldr As IO.DirectoryInfo = New IO.DirectoryInfo(Me.RootSVNPath)
			Dim ret As String = fldr.Parent.FullName & "\"
			Return ret

		End Get
	End Property

	''' <summary>
	''' The working file path is always in the parent directory of root svn
	''' </summary>
	Public Function getAccessDatabaseFullName() As String

        Return New FileInfo(Me.RootSVNPath & "\..\" & Me.projectInfo.AccessDatabaseName).FullName

	End Function


	Public Sub loadConfigFile()

		Me.projectInfo = New AccessSvnProjectInfo
		Dim x As XmlSerializer = New XmlSerializer(Me.projectInfo.GetType())
		Dim stream As FileStream = New FileStream(Me.xmlConfigFilename, FileMode.Open)
		Try

			Me.projectInfo = CType(x.Deserialize(stream), AccessSvnProjectInfo)

		Finally
			stream.Close()
			stream.Dispose()
		End Try

	End Sub

	Shared Function getTransformerProvider(ByVal AccessDatabaseName As String) As IAccessTransformerProvider
		If AccessDatabaseName.ToLower.EndsWith(STR_ADP) Then
			Return New ADPTransformerProvider
		Else
			Return New MDBTransformerProvider
		End If

	End Function

	Function isADPProject() As Boolean
		Return getAccessDatabaseFullName.ToLower.EndsWith(STR_ADP)
	End Function

	''' <summary>
	''' Returns True if the SVN sources do not exist and will be created during this export.
	''' </summary>
	Function isNew() As Boolean

		Return Directory.Exists(Me.RootSVNPath & "\DB")

    End Function

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="appl">Access Application</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function getAccessOpenFilePath(ByVal appl As Application) As String
        try
            If appl.CurrentDb IsNot Nothing Then Return appl.CurrentDb.Name
        Catch ex As Exception
            'ignore error
        End Try
        Try
            If appl.CurrentProject IsNot Nothing Then Return appl.CurrentProject.Name
        Catch ex As Exception
            'ignore error
        End Try
        
        Return String.Empty

    End Function

	''' <summary>
	''' Return current reference to access application if running
	''' </summary>
	Public Shared function getRunningAccessComReference() As Access.Application

		Dim MyXL As Object = Nothing
		Dim accessClassId As String = "Access.Application"

		Try	' Defer error trapping.
			
			MyXL = Marshal.GetActiveObject(accessClassId)
			Return CType(MyXL, Access.Application)
		
		Catch e As Exception
			Return nothing

		End Try


    End Function


    Public Function getAccessProperty(ByVal app As Access.Application, ByVal propName As String) As String

        Dim exists As Boolean = False
        Dim i As Integer
        For i = 0 To app.CurrentProject.Properties.Count - 1
            If app.CurrentProject.Properties(i).Name = propName Then
                Return CStr(app.CurrentProject.Properties(i).Value)

            End If
        Next

        Return String.Empty

    End Function
    Public Sub AddOrChangeAccessProperty(ByVal app As Access.Application, ByVal propName As String, ByVal propvalue As String)

        Dim exists As Boolean = False
        Dim i As Integer
        For i = 0 To app.CurrentProject.Properties.Count - 1
            If app.CurrentProject.Properties(i).Name = propName Then
                app.CurrentProject.Properties(i).Value = propvalue
                exists = True
            End If
        Next

        If Not exists Then
            Call app.CurrentProject.Properties.Add(propName, propvalue)
        End If

    End Sub

    Public Function determineTortoisePath() As String

        Dim registryKey As RegistryKey
        If (Environment.Is64BitOperatingSystem = True) Then
            registryKey = registryKey.OpenBaseKey( _
             Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64)
        Else
            registryKey = registryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, _
              RegistryView.Registry32)
        End If

        If (registryKey Is Nothing) Then
            Throw New ApplicationException("Cannot open LocalMachine registry key to read Tortoise SVN Path")
        End If

        Dim regKey As RegistryKey = registryKey.OpenSubKey("SOFTWARE\TortoiseSVN", False)

        If (regKey Is Nothing) Then
            Throw New ApplicationException("SOFTWARE\TortoiseSVN registry key does not exit.  Have you installed Tortoise SVN?")
        End If

        Return CStr(regKey.GetValue("ProcPath", String.Empty))

    End Function
End Class
